package cn.xwt.weidisk.config;

import cn.xwt.weidisk.filter.MyCodeFilter;
import cn.xwt.weidisk.handler.MyAuthenticationEntryPoint;
import cn.xwt.weidisk.handler.MyAuthenticationFailureHandler;
import cn.xwt.weidisk.handler.MyAuthenticationSuccessHandler;
import cn.xwt.weidisk.handler.MyLogoutSuccessHandler;
import cn.xwt.weidisk.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;

/**
 * @author 薛慰涛
 * springsecurity配置
 */
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UserService userService;

    @Resource
    private DataSource dataSource;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
   public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
//        tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 跨域
        http.cors().configurationSource(corsConfigurationSource());
        // 关闭crsf 开启crsf会阻拦除get外的请求
        http.csrf().disable();
        // 配置权限
        http.authorizeRequests()
                .antMatchers("/open/**").permitAll()
                .antMatchers("/system/**").hasRole("user")
                .antMatchers("/admin/**").hasRole("admin");

        // 配置退出登录
        http.logout()
                .logoutUrl("/login-out")
                .logoutSuccessHandler(new MyLogoutSuccessHandler())
                .permitAll();

        // 配置验证码过滤器
        http.addFilterBefore(myCodeFilter(), UsernamePasswordAuthenticationFilter.class);

        http.formLogin()
                .loginProcessingUrl("/login")
                .permitAll()
                .usernameParameter("email")
                .failureHandler(new MyAuthenticationFailureHandler())
                .successHandler(new MyAuthenticationSuccessHandler());

        // 没有认证时调用处理器
        http.exceptionHandling().authenticationEntryPoint(new MyAuthenticationEntryPoint());

        http.rememberMe()
                .tokenRepository(persistentTokenRepository())
                .rememberMeCookieName("wei_token")
                .rememberMeParameter("remember")
                .key("xueweitao")
                .tokenValiditySeconds(60 * 60 * 24 * 7)
                .userDetailsService(userService);
    }

    /**
     * 跨域配置
     * @return CorsConfigurationSource
     */
    private CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
//        configuration.addAllowedOrigin("http://106.55.34.216");
//        configuration.addAllowedOrigin("http://disk.xueweitao.xyz");
        configuration.addAllowedOrigin("http://192.168.31.164:8080");
//        configuration.addAllowedOrigin("*");
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        configuration.setAllowedMethods(Arrays.asList("POST", "PUT", "DELETE", "GET"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    /**
     * 验证码过滤器
     *
     * @return MyCodeFilter
     */
    @Bean
    MyCodeFilter myCodeFilter() {
        return new MyCodeFilter();
    }
}
